import { onBeforeUnmount, readonly, ref, shallowRef, watch } from 'vue'

import { type GisKey, type GisRef, KEY, Platform } from '@ol/define'
import { setupBaseLayer, setupMap } from '@ol/services'
import type { ILayerOptions, IViewerOptions } from '@ol/types'
import { isNil } from 'es-toolkit'

/**
 * Vue 3 Hook：用于初始化并管理 OpenLayers 地图实例。
 *
 * 该 Hook 封装了地图的生命周期管理（初始化、绑定 DOM、添加基础图层、释放资源）。
 * 适用于需要在 Vue 组件中集成 OpenLayers 地图的场景。
 *
 * @param viewerOptions - 地图初始化配置（中心点、缩放、投影等）
 * @param baseLayerOptions - 基础图层配置（如 WMTS/WMS 等）
 * @param key - 地图实例标识（默认值来自 `@ol/define`）
 * @param platform - 地图平台类型，默认 `Platform.OL`
 * @param autoDispose - 是否在组件销毁时销毁地图，默认 true
 *
 * @returns 一个对象，包含：
 * - `gis` - 只读的地图引用（`GisRef | null`）
 * - `inited` - 地图是否已完成初始化
 * - `disposed` - 地图是否已被释放
 * - `setTarget` - 将地图绑定到指定 DOM 元素的方法
 * - `dispose` - 释放地图资源的方法
 *
 * @example
 * ```ts
 * const { gis, inited, setTarget, dispose } = useMap(viewerOptions, baseLayerOptions)
 * setTarget 绑定到某个 div 上
 * ```
 */
export default function useMap(
  viewerOptions: IViewerOptions,
  baseLayerOptions: ILayerOptions,
  key: GisKey = KEY,
  platform = Platform.OL,
  autoDispose = true,
) {
  const inited = ref(false)
  const disposed = ref(false)
  const gis = shallowRef<GisRef | null>(null)

  watch(gis, (v) => {
    if (isNil(v)) return
    console.log(v)
    setupBaseLayer(baseLayerOptions, key).then(() => {
      inited.value = true
      disposed.value = false
    })
  })

  if (autoDispose !== false) {
    onBeforeUnmount(dispose)
  }

  return {
    /**
     * 是否初始化完成
     */
    inited: readonly(inited),
    /**
     * 地图是否销毁
     */
    disposed: readonly(disposed),
    /**
     * 设置用于初始地图的 div
     */
    setTarget,
    /**
     * 销毁地图实例
     */
    dispose,
    /**
     * 设置底图
     */
    setupBase,
    gis: readonly(gis),
  }

  function setupBase(baseOptions: ILayerOptions) {
    return setupBaseLayer(baseOptions, key)
  }

  /**
   * 将地图绑定到指定的 HTML 元素。
   *
   * 如果地图已初始化，或者 `ele` 为 `null`，则不会重复初始化。
   * 调用此方法会根据 `viewerOptions` 初始化地图实例，
   * 并加载基础图层（`baseLayerOptions`）。
   *
   * @param ele - 用于承载地图的 DOM 元素
   */
  function setTarget(ele: HTMLElement | null): void {
    if (!ele || inited.value) return
    //console.log({ ele, inited: inited.value })
    gis.value = setupMap(ele, viewerOptions, key, platform)
  }

  /**
   * 释放地图资源并重置状态。
   *
   * 调用此方法会：
   * - 停止地图渲染
   * - 清空 `gis` 引用
   * - 将 `inited` 设为 `false`
   * - 将 `disposed` 设为 `true`
   */
  function dispose(): void {
    disposed.value = true
    if (gis.value) {
      inited.value = false
      //console.log({ disposed: disposed.value, inited: inited.value }, 'dispose')
      gis.value.dispose().then(() => {
        gis.value = null
        //console.log({ disposed: disposed.value, inited: inited.value }, 'dispose then')
      })
    }
  }
}
